package com.ruowei.security;

import com.ruowei.common.error.exception.CommonException;
import com.ruowei.common.error.exception.DataNotFoundException;
import com.ruowei.modules.foodOrder.domain.Couriers;
import com.ruowei.modules.foodOrder.domain.Merchant;
import com.ruowei.modules.foodOrder.repository.CouriersRepository;
import com.ruowei.modules.foodOrder.repository.MerchantRepository;
import com.ruowei.modules.sys.domain.enumeration.UserStatusType;
import com.ruowei.modules.sys.domain.enumeration.UserType;
import com.ruowei.modules.sys.domain.table.SysOffice;
import com.ruowei.modules.sys.domain.table.SysUserTable;
import com.ruowei.modules.sys.repository.SysUserRoleRepository;
import com.ruowei.modules.sys.repository.entity.SysEmployeeRepository;
import com.ruowei.modules.sys.repository.table.SysUserTableRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Authenticate a user from the database.
 */
@Component("userDetailsService")
public class DomainUserDetailsService implements UserDetailsService {

    private final Logger log = LoggerFactory.getLogger(DomainUserDetailsService.class);
    private final SysUserTableRepository sysUserTableRepository;
    private final SysUserRoleRepository sysUserRoleRepository;
    private final SysEmployeeRepository sysEmployeeRepository;
    private final CouriersRepository couriersRepository;
    private final MerchantRepository merchantRepository;

    public DomainUserDetailsService(SysUserTableRepository sysUserTableRepository, SysUserRoleRepository sysUserRoleRepository, SysEmployeeRepository sysEmployeeRepository, CouriersRepository couriersRepository, MerchantRepository merchantRepository) {
        this.sysUserTableRepository = sysUserTableRepository;
        this.sysUserRoleRepository = sysUserRoleRepository;
        this.sysEmployeeRepository = sysEmployeeRepository;
        this.couriersRepository = couriersRepository;
        this.merchantRepository = merchantRepository;
    }

    @Override
    @Transactional
    public UserDetails loadUserByUsername(final String login) {
        log.debug("Authenticating {}", login);

        return sysUserTableRepository.findOneByLoginCodeAndStatus(login, UserStatusType.NORMAL)
            .map(sysUser -> createSpringSecurityUser(login, sysUser))
            .orElseThrow(() -> new UsernameNotFoundException("用户名或密码错误"));

    }

    private UserModel createSpringSecurityUser(String login, SysUserTable sysUser) {
        List<GrantedAuthority> grantedAuthorities =
            sysUserRoleRepository.getAllRoleCodeByUserId(sysUser.getId())
                .stream().map(SimpleGrantedAuthority::new)
                .distinct().collect(Collectors.toList());
        SysOffice sysOffice = null;
        if (sysUser.getUserType().equals(UserType.COURIER)) {
            Optional<Couriers> opt = couriersRepository.findOneByCourierCode(sysUser.getUserCode());
            if (!opt.isPresent()) {
                throw new CommonException("账户已经删除");
            }
            if (!opt.get().isAvailableStatus()) {
                throw new CommonException("账号已停用");
            }
        } else if (sysUser.getUserType().equals(UserType.BUSINESS)) {
            Optional<Merchant> opt = merchantRepository.findOneByMerchantCodeAndStatusNot(sysUser.getUserCode(), "删除");
            if (!opt.isPresent()) {
                throw new CommonException("账户已经删除");
            }
        } else if (sysUser.getUserType().equals(UserType.STATION) || sysUser.getUserType().equals(UserType.ADMIN)) {
            //不做处理
        } else {
            sysOffice = sysEmployeeRepository.findById(sysUser.getRefCode())
                .map(sysEmployee -> {
                    // 校验在职状态
//                if (sysEmployee.getPersonnelId() != null) {
//                    personnelRepository.findById(sysEmployee.getPersonnelId())
//                        .ifPresent(personnel -> {
//                            if (!PersonnelStatus.ONJOB.equals(personnel.getStatus())) {
//                                throw new LockedException("该用户已停用，请联系系统管理员");
//                            }
//                        });
//                }
                    return sysEmployee.getOffice();
                })
                .orElseThrow(() -> new DataNotFoundException("未找到机构信息"));
        }

        return new UserModel(
            sysUser.getLoginCode(),
            sysUser.getPassword(),
            grantedAuthorities,
            sysUser.getId(),
            sysUser.getUserName(),
            sysUser.getUserCode(),
            sysOffice == null ? "" : sysOffice.getOfficeCode(),
            (sysUser.getRefCode() == null) ? -1 : sysUser.getRefCode());
    }
}
